<!--
 * @Author: linZeJian
 * @Date: 2023-07-26 10:52:34
 * @LastEditors: linZeJian
 * @LastEditTime: 2023-08-17 16:17:25
 * @Description: 
-->
<template>
  <div>
    <!-- 自定义提示弹窗 -->
    <div v-if="showMessage" class="floating-message-dialog">
      <div class="floating-message-box">
        <h4>消息弹窗</h4>
        <div class="message-content">
          {{ message }}
        </div>
      </div>
    </div>

    <!-- 替代原生 window.alert 弹窗功能的组件 -->
    <!-- SweetAlert2:https://sweetalert2.github.io/#examples -->
    <!-- Vue-Sweetalert2:https://github.com/avil13/vue-sweetalert2 -->
    <!-- Element UI 的 MessageBox -->

    <!-- 静态固定位置 -->
    <!-- <div
      v-draggable
      class="floating-button"
      :style="{
        bottom: position.bottom + 'px',
        right: position.right + 'px',
      }"
      @click="handleClick"
    >
      <slot></slot>
      <img
        class="floating-logo"
        :src="require('../../assets/img/customer.png')"
        alt=""
      />
    </div> -->

    <!-- vuedraggable实现div 返回首页图标dom节点 浮动节点可拖动后触发拖动事件动态改变浮动位置,只能实现列表数据的拖动 -->
    <!-- <draggable
      v-model="position"
      handle=".floating-button"
      animation="300"
      @end="onDragEnd"
    >
      <div
        class="floating-button"
        :style="{
          bottom: position.bottom + 'px',
          right: position.right + 'px',
        }"
        @click="handleClick"
      >
        <slot></slot>
        <img
          class="floating-logo"
          :src="require('../../assets/img/customer.png')"
          alt=""
        />
      </div>
    </draggable> -->

    <!-- vue 悬浮球(带自动吸附功能) https://blog.csdn.net/qq_34684704/article/details/119952404 -->
    <div
      ref="floatDrag"
      class="floating-button"
      :style="{ left: left + 'px', top: top + 'px', zIndex: zIndex }"
      @touchmove.prevent
      @mousemove.prevent
      @mousedown="mouseDown"
      @mouseup="mouseUp"
      @click="moveOverflow"
    >
      <slot></slot>
      <img
        class="floating-logo"
        :src="require('../assets/customer.png')"
        alt=""
      />
    </div>
  </div>
</template>

<script>
// vuedraggable实现div 返回首页图标dom节点 浮动节点可拖动后触发拖动事件动态改变浮动位置,只能实现列表数据的拖动
// vue-drag-resize是一个Vue.js组件，用于实现可拖拽和可调整大小的DOM元素
// import draggable from "vuedraggable";

// sweetalert2
import Swal from "sweetalert2";
export default {
  name: "cs-xuanfuqiu",
  components: {
    // draggable
  },
  props: {
    urlAndParams: {
      type: String,
      default: "",
    },
    // 低版本企业微信pc端（49） 无法使用该组件，得使用alert
    alertType: {
      type: String,
      default: "sweetalert2",
    },

    // 悬浮球
    // handlepaly()父组件点击事件
    distanceRight: {
      type: Number,
      default: 0,
    },
    distanceBottom: {
      type: Number,
      default: 20,
    },
    isScrollHidden: {
      type: Boolean,
      default: false,
    },
    isCanDraggable: {
      type: Boolean,
      default: true,
    },
    zIndex: {
      type: Number,
      default: 99999,
    },
    value: {
      type: String,
      default: "悬浮球！",
    },
  },
  data() {
    return {
      showMessage: false,
      message: "message",
      alertTypeOwn: "sweetalert2",

      // vuedraggable
      position: {
        bottom: 20, // 节点距离底部的距离
        right: 20, // 节点距离右侧的距离
      },

      // 悬浮球
      clientWidth: null,
      clientHeight: null,
      left: 0,
      top: 0,
      timer: null,
      currentTop: 0,
      mousedownX: 0,
      mousedownY: 0,
    };
  },
  computed: {},
  created() {
    this.clientWidth = document.documentElement.clientWidth;
    this.clientHeight = document.documentElement.clientHeight;
  },
  mounted() {
    this.isCanDraggable &&
      this.$nextTick(() => {
        this.floatDrag = this.$refs.floatDrag;
        // 获取元素位置属性
        this.floatDragDom = this.floatDrag.getBoundingClientRect();
        // 设置初始位置
        this.left =
          this.clientWidth - this.floatDragDom.width - this.distanceRight;
        this.top =
          this.clientHeight - this.floatDragDom.height - this.distanceBottom;
        this.initDraggable();
      });
    this.isScrollHidden && window.addEventListener("scroll", this.handleScroll);
    window.addEventListener("resize", this.handleResize);
  },
  beforeUnmount() {
    window.removeEventListener("scroll", this.handleScroll);
    window.removeEventListener("resize", this.handleResize);
  },
  watch: {},
  methods: {
    // 查看企业微信版本与企业微信浏览器内核版本
    // window.alert(`企业微信版本: ${getEnterpriseWeChatVersion()}`);
    // window.alert(`企业微信浏览器内核版本: ${getEnterpriseWeChatChromeVersion()}`);
    /**
     * @description:  js获取企业微信版本
     * @return {*}
     */
    getEnterpriseWeChatVersion() {
      let match = window.navigator.userAgent.match(/wxwork\/(\d+\.\d+\.\d+)/i);
      return match ? match[1] : false;
    },

    /**
     * @description:  js获取企业微信浏览器内核版本
     * @return {*}
     */
    getEnterpriseWeChatChromeVersion() {
      const match = window.navigator.userAgent.match(/Chrome\/(\d+)\./);
      return match ? parseInt(match[1], 10) : false;
    },
    /**
     * @description: 按钮点击事件
     * @return {*}
     */
    handleClick() {
      // 悬浮按钮点击事件
      console.log(
        '悬浮按钮点击事件--子组件触发父组件事件（this.$emit("clickBtn")）'
      );

      // 自定义提示弹窗
      // this.showMessage = true;

      // 自定义提示弹窗2
      // this.customAlert("11111")

      // uniapp开发小程序与app，非web端，不支持 window、document、navigator 等浏览器的 js API；
      // window.alert(`message`);

      console.log("父组件传参--urlAndParams", this.urlAndParams);
      // 定义按钮点击事件
      let url = `${this.getCurrentDomain()}${this.urlAndParams}`;
      console.log("悬浮按钮点击事件--url", url);
      // this.requestUrl(url);
      // this.$emit("clickBtn");

      // 企业微信版本过低判断提示：通过企业微信浏览器内裤版本判断（旧49，新96）,企业微信版本无法对版本号做对比处理
      const enterpriseWeChatChromeVersion = this.getEnterpriseWeChatChromeVersion();
      if (enterpriseWeChatChromeVersion && enterpriseWeChatChromeVersion < 80) {
        this.alertTypeOwn = "alert";
        window.alert(
          `当前企业微信浏览器内核版本(${enterpriseWeChatChromeVersion}) < 80 较低，请检查更新！`
        );
      }

      // window.confirm 方法会弹出一个确认框，包含“确认”和“取消”两个按钮
      if (this.alertTypeOwn == "alert") {
        // 低版本企业微信pc端（49） 无法使用该组件
        const confirmed = window.confirm("确定通知客服吗？");
        if (confirmed) {
          // 执行确认操作
          this.requestUrl(url, "alert");
          this.$emit("clickBtn");
        } else {
          // 执行取消操作
        }
      } else {
        // 高于96的版本，但是还是想使用alert
        if (this.alertType == "alert") {
          const confirmed = window.confirm("确定通知客服吗？");
          if (confirmed) {
            // 执行确认操作
            this.requestUrl(url, "alert");
            this.$emit("clickBtn");
          } else {
            // 执行取消操作
          }
        }
        // sweetalert2
        if (this.alertType == "sweetalert2") {
          Swal.fire({
            title: "报障通知",
            text: "确定通知客服吗？",
            icon: "warning",
            showCancelButton: true,
            confirmButtonColor: "#3085d6",
            cancelButtonColor: "#d33",
            confirmButtonText: "确认",
            cancelButtonText: "取消",
          }).then((result) => {
            if (result.isConfirmed) {
              // Swal.fire("Deleted!", "Your file has been deleted.", "success");

              // 执行确认操作
              this.requestUrl(url, "sweetalert2");
              this.$emit("clickBtn");
            }
          });
        }
      }
    },
    /**
     * @description: 获取本项目运行域名
     * @return {*}
     */
    getCurrentDomain() {
      return window.location.protocol + "//" + window.location.host;
    },
    /**
     * @description: XMLHttpRequest处理点击事件
     * @param {*} type
     * @param {*} url
     * @param {*} resType
     * @param {*} jsonData
     * @return {*}
     */
    requestUrl(url, type = "alert", resType = "GET", jsonData = "") {
      const xhr = new XMLHttpRequest();
      xhr.open(resType, url, true);
      xhr.responseType = "blob"; // 表示返回的数据是二进制流对象
      // 携带请求头
      // h5测试
      if (process.env.NODE_ENV == "development") {
        if (process.env.VUE_APP_TOKEN) {
          xhr.setRequestHeader(
            "Authorization",
            `Bearer ${process.env.VUE_APP_TOKEN}`
          );
          xhr.setRequestHeader("X-Oars-Token", `${process.env.VUE_APP_TOKEN}`);
        }
      } else {
        // 上线阶段,自动获取登录的 token localStorage Key:  IDAAS_BEARER_TOKEN
        let IDAAS_BEARER_TOKEN =
          localStorage.getItem("IDAAS_BEARER_TOKEN") || "";
        if (IDAAS_BEARER_TOKEN) {
          xhr.setRequestHeader("Authorization", `Bearer ${IDAAS_BEARER_TOKEN}`);
        }
      }

      // handleStateChange 中判断请求的状态，并处理请求失败的情况
      // 使用原生 window.alert 弹窗功能
      const handleStateChange = function (event) {
        if (xhr.readyState === XMLHttpRequest.DONE) {
          if (xhr.status === 200) {
            // 原生数据流处理
            // 请求成功，处理响应数据
            console.log("xhr.response", xhr.response);
            // 创建一个 FileReader 对象
            const reader = new FileReader();
            // 当读取完成时执行的回调函数
            reader.onload = function () {
              // 读取结果是一个字符串
              const result = reader.result;
              console.log("xhr.response--result", result);
              // console.log(result.indexOf('"code":-1'))
              // 处理请求成功但是"code":-1'报错
              if (result.indexOf('"code":-1') != -1) {
                // window.alert(`操作失败！${result}`);
                if (type == "alert") {
                  window.alert(`操作失败，code：-1，请检查接口！`);
                }
                if (type == "sweetalert2") {
                  Swal.fire("操作失败", "code：-1，请检查接口！", "error");
                }
              } else if (result.indexOf('"error":1') != -1) {
                // window.alert(`操作失败！${result}`);
                if (type == "alert") {
                  window.alert(
                    `操作失败，error: 1，应用标识是否正确，请检查接口！`
                  );
                }
                if (type == "sweetalert2") {
                  Swal.fire(
                    "操作失败",
                    "error: 1，应用标识是否正确，请检查接口！",
                    "error"
                  );
                }
              } else if (
                result.indexOf("We're sorry") != -1 ||
                result.indexOf("<!DOCTYPE html>") != -1
              ) {
                // window.alert(`操作失败！${result}`);
                if (type == "alert") {
                  window.alert(`操作失败，请检查接口！`);
                }
                if (type == "sweetalert2") {
                  Swal.fire("操作失败", "请检查接口！", "error");
                }
              } else {
                // window.alert(`操作成功！${result}`);
                if (type == "alert") {
                  window.alert(
                    `操作成功！已通知相关人员，请耐心等待工程师联系您`
                  );
                }
                if (type == "sweetalert2") {
                  Swal.fire(
                    "操作成功",
                    "已通知相关人员，请耐心等待工程师联系您",
                    "success"
                  );
                }
              }
            };
            // 读取 Blob 对象的内容
            reader.readAsText(xhr.response);
          } else {
            // 创建一个 FileReader 对象
            const reader = new FileReader();
            // 当读取完成时执行的回调函数
            reader.onload = function () {
              // 读取结果是一个字符串
              const result = reader.result;
              console.log("xhr.error--result", result);
              // window.alert(`操作失败！${result}`);
              if (type == "alert") {
                window.alert(`操作失败，状态码 status != 200，请检查接口！`);
              }
              if (type == "sweetalert2") {
                Swal.fire(
                  "操作失败",
                  "状态码 status != 200，请检查接口！",
                  "error"
                );
              }
            };
            // 读取 Blob 对象的内容
            reader.readAsText(xhr.response);
          }
        }
      };
      xhr.addEventListener("readystatechange", handleStateChange);
      if (resType == "GET") {
        xhr.send();
      } else {
        xhr.send(jsonData);
      }
    },

    /**
     * @description: 使用js代码重写qs.stringify():将对象序列化成url的形式；以&进行拼接的方法，包括数组传参
     * @description: get请求映射params参数，params参数url参数转码
     * @param {*} params
     * @return {*}
     */
    serializeParams(params) {
      let paramsStr = "?";

      for (const propName of Object.keys(params)) {
        const value = params[propName];
        const part = encodeURIComponent(propName) + "=";

        if (value !== null && typeof value !== "undefined") {
          if (Array.isArray(value)) {
            value.forEach((val) => {
              paramsStr += part + encodeURIComponent(val) + "&";
            });
          } else if (typeof value === "object") {
            for (const key of Object.keys(value)) {
              const subPropName = `${propName}[${key}]`;
              const subPart = encodeURIComponent(subPropName) + "=";
              paramsStr += subPart + encodeURIComponent(value[key]) + "&";
            }
          } else {
            paramsStr += part + encodeURIComponent(value) + "&";
          }
        }
      }

      return paramsStr.slice(0, -1);
    },

    /**
     * @description: 自定义提示弹窗2
     * @description: window.alert方法时不显示包含域名的通知文字，使用自定义弹窗来替代window.alert
     * @param {*} message
     * @return {*}
     */
    customAlert(message) {
      var alertBox = document.createElement("div");
      alertBox.style.position = "fixed";
      alertBox.style.top = "50%";
      alertBox.style.left = "50%";
      alertBox.style.transform = "translate(-50%, -50%)";
      alertBox.style.background = "#f9f9f9";
      alertBox.style.border = "1px solid #ccc";
      alertBox.style.padding = "20px";
      alertBox.style.zIndex = "99999";
      alertBox.style.borderRadius = "10px";

      var messageText = document.createElement("p");
      messageText.textContent = message;

      // 关闭弹窗
      var closeButton = document.createElement("button");
      closeButton.textContent = "Close";
      closeButton.addEventListener("click", function () {
        document.body.removeChild(alertBox);
      });

      alertBox.appendChild(messageText);
      alertBox.appendChild(closeButton);
      document.body.appendChild(alertBox);
    },
    // end 基本事件--------------------------------------------------------------------------------

    // vuedraggable--------------------------------------------------------------------------------
    /**
     * @description: 浮动节点可拖动后触发拖动事件动态改变浮动位置
     * @param {*} event
     * @return {*}
     */
    onDragEnd(event) {
      console.log("event", event);
      // parentElement undefined
      const { bottom, right } =
        event.source.parentElement.getBoundingClientRect();
      this.position.bottom = window.innerHeight - bottom;
      this.position.right = window.innerWidth - right;
    },
    // end vuedraggable--------------------------------------------------------------------------------

    // 悬浮球 --------------------------------------------------------------------------------
    /**
     * 设置滚动监听
     * 设置滚动时隐藏悬浮按钮，停止时显示
     */
    handleScroll() {
      this.timer && clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.handleScrollEnd();
      }, 200);
      this.currentTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (this.left > this.clientWidth / 2) {
        // 判断元素位置再左侧还是右侧
        this.left = this.clientWidth + this.floatDragDom.width;
      } else {
        this.left = -this.floatDragDom.width;
      }
    },
    /**
     * 滚动结束
     */
    handleScrollEnd() {
      let scrollTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (scrollTop === this.currentTop) {
        console.log(this.left);
        if (this.left > this.clientWidth / 2) {
          // 判断元素位置再左侧还是右侧
          this.left = this.clientWidth - this.floatDragDom.width;
        } else {
          this.left = 0;
        }
        clearTimeout(this.timer);
      }
    },
    /**
     * 窗口resize监听
     */
    handleResize() {
      // this.clientWidth = document.documentElement.clientWidth;
      // this.clientHeight = document.documentElement.clientHeight;
      this.checkDraggablePosition();
    },
    /**
     * 初始化draggable
     */
    initDraggable() {
      this.floatDrag.addEventListener("touchstart", this.toucheStart);
      this.floatDrag.addEventListener("touchmove", (e) => this.touchMove(e));
      this.floatDrag.addEventListener("touchend", this.touchEnd);
    },
    mouseDown(e) {
      const event = e || window.event;
      this.mousedownX = event.screenX;
      this.mousedownY = event.screenY;
      const that = this;
      let floatDragWidth = this.floatDragDom.width / 2;
      let floatDragHeight = this.floatDragDom.height / 2;
      if (event.preventDefault) {
        event.preventDefault();
      }
      this.canClick = false;
      this.floatDrag.style.transition = "none";
      document.onmousemove = function (e) {
        var event = e || window.event;
        // console.log("event", event);
        that.left = event.clientX - floatDragWidth;
        that.top = event.clientY - floatDragHeight;
        if (that.left < 0) that.left = 0;
        if (that.top < 0) that.top = 0;
        if (that.left >= that.clientWidth - floatDragWidth * 2) {
          that.left = that.clientWidth - floatDragWidth * 2;
        }
        if (that.top >= that.clientHeight - floatDragHeight * 2) {
          that.top = that.clientHeight - floatDragHeight * 2;
        }
        // 移动后移除移动监听事件,解决鼠标移出拖动事件还在
        // document.onmousemove = null;
        // 直接清除有时会导致按钮拖动很卡
        // return
        if (that.top == 0 || that.top < 0) {
          // 判断是否超出屏幕上沿
          that.top = 0;
          that.left = that.clientWidth - floatDragWidth * 2;
          document.onmousemove = null;
        }
        if (that.top + that.floatDragDom.height >= that.clientHeight) {
          // 判断是否超出屏幕下沿
          that.left = that.clientWidth - floatDragWidth * 2;
          that.top = that.clientHeight - that.floatDragDom.height;
          document.onmousemove = null;
        }
      };
    },
    mouseUp(e) {
      const event = e || window.event;
      //判断只是单纯的点击，没有拖拽
      if (
        this.mousedownY == event.screenY &&
        this.mousedownX == event.screenX
      ) {
        // this.$emit("handlepaly");
        this.handleClick();
        // @click="handleClick" dom使用@click在鼠标按下拖动过程中松开后回自动执行
      }
      document.onmousemove = null;
      this.checkDraggablePosition();
      this.floatDrag.style.transition = "all 0.3s";
    },
    toucheStart() {
      this.canClick = false;
      this.floatDrag.style.transition = "none";
    },
    touchMove(e) {
      const event = e || window.event;
      this.canClick = true;
      if (e.targetTouches.length === 1) {
        // 单指拖动
        let touch = event.targetTouches[0];
        this.left = touch.clientX - this.floatDragDom.width / 2;
        this.top = touch.clientY - this.floatDragDom.height / 2;
      }
    },
    touchEnd() {
      if (!this.canClick) return; // 解决点击事件和touch事件冲突的问题
      this.floatDrag.style.transition = "all 0.3s";
      this.checkDraggablePosition();
    },
    /**
     * 判断元素显示位置
     * 在窗口改变和move end时调用
     */
    checkDraggablePosition() {
      if (this.left + this.floatDragDom.width / 2 >= this.clientWidth / 2) {
        // 判断位置是往左往右滑动
        this.left = this.clientWidth - this.floatDragDom.width;
      } else {
        this.left = 0;
      }
      if (this.top < 0) {
        // 判断是否超出屏幕上沿
        this.top = 0;
      }
      if (this.top + this.floatDragDom.height >= this.clientHeight) {
        // 判断是否超出屏幕下沿
        this.top = this.clientHeight - this.floatDragDom.height;
      }
      // 鼠标拖动事件还在
      // document.onmousemove ==  null; 要清除
    },
    moveOverflow() {
      console.log("1111", 1111);
    },
    // end 悬浮球 --------------------------------------------------------------------------------
  },
};
</script>

<style>
.floating-message-dialog {
  /* position: fixed;
  bottom: 0px;
  right: 0px;
  z-index: 100000;
  width: 100vw;
  height: 100vh;
  background-color: rgb(164, 164, 164);
  text-align: center;
  opacity: 0; */
}
.floating-message-dialog .floating-message-box {
  position: fixed;
  top: 10px;
  right: 10px;
  z-index: 100000;
  /* width: 60vw; */
  /* height: 60vh; */
  max-width: 80vw;
  border-radius: 10px;
  background-color: rgb(255, 255, 255);
  color: #000000;
  font-size: 18px;
  text-align: center;
  line-height: 20px;
  opacity: 1;
  margin: auto;
  margin-top: 20px;
  padding: 20px;
  box-sizing: border-box;
  border: 1px solid #ebeef5;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  transition: opacity 0.3s, transform 0.3s, left 0.3s, right 0.3s, top 0.4s,
    bottom 0.3s;
}
.floating-message-dialog .floating-message-box .message-content {
  color: #747474;
  font-size: 14px;
  line-height: 18px;
  margin-top: 20px;
}
.floating-button {
  position: fixed;
  /* bottom: 20px;
  right: 20px; */
  z-index: 99999;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: #89b9ff;
  color: #fff;
  font-size: 24px;
  text-align: center;
  cursor: pointer;
  opacity: 0.8;
  box-shadow: 0px 0px 6px 1px #b7b7b7;
}
.floating-button .floating-logo {
  margin-top: 10px;
  width: 30px;
  height: 30px;
}
</style>
